﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IBS.Model;
using IBS.Dal;
using IBS.Model.Base;
using IBS.Bll.Tools;
using IBS.ServiceContracts;
using log4net;

namespace IBS.Bll.KnowledgeBase
{
    public class KnowledgeBaseService : ServiceBase, IKnowledgeBaseService
    {
        private readonly IAddressService _addressService;

        #region Fields

        private static readonly ILog log = LogManager.GetLogger(typeof(KnowledgeBaseService));
        private ClientValidator clientValidator;
        #endregion

        #region Constructors

        public KnowledgeBaseService(IIbsContext context, IAddressService addressService)
            : base(context)
        {
            _addressService = addressService;
            clientValidator = new ClientValidator(context);
        }

        #endregion
        
        #region Members

        public void CreateClient(Client clientInfo, int homeAddressId, int regAddressId, string login)
        {
            try
            {
                log.InfoFormat("CreateClient FirstName={0}, LastName ={1}, PatronymicName={2}, PassportNumber ={3}, PassportSeries = {4} started ...",
                    clientInfo.FirstName, clientInfo.LastName, clientInfo.Patronymic, clientInfo.PassportNumber, clientInfo.PassportSeries);
                clientInfo.UpdateLogin = login;


                //Validation

                if (clientValidator.ClientWithSamePassportExists(clientInfo))
                {
                    throw new BusinessException("Client already exists");
                };

                var homeAddress = _addressService.GetAddressById(homeAddressId);
                var regAddress = _addressService.GetAddressById(regAddressId);
                clientInfo.Address = homeAddress;
                clientInfo.Address1 = regAddress;
                //clientInfo.DateOfBirth = DateTime.Now;
                _context.Clients.AddObject(clientInfo);

                log.InfoFormat("Save client into db...");
                _context.SaveChanges();
                log.InfoFormat("Client has been saved");
            }

            catch (Exception exception)
            {
                log.Error(exception.Message, exception);
                throw;
            }
        }

        public Client GetClientById(int clientId)
        {
            try
            {
                return _context.Clients.Single(c => c.Id == clientId);
            }
            catch (InvalidOperationException)
            {
                throw new BusinessException("Client does not exist");
            }
        }

        public IList<Client> GetClients(Func<Client, bool> predicate = null, int? pageNumber = null)
        {
            IList<Client> result;
            log.InfoFormat("Get Clients By Criteria...");
            var clientsByCriteria = _context.Clients.GetByCriteria(pageNumber, predicate);

            result = clientsByCriteria.ToList();
            log.InfoFormat("Clients has been got");
            return result;
        }

        public void UpdateClient(Client client, string login)
        {
            log.InfoFormat("Update Client with LastName = {0}", client.LastName);
            try
            {
                //Validate
                if (!clientValidator.CanUpdateClient(client))
                {
                    throw new BusinessException("Client can't be updated. Some field is invalid");
                }

                client.UpdateLogin = login;
                //context.ObjectStateManager.ChangeObjectState(client, System.Data.EntityState.Modified);
                _context.SaveChanges();
            }

            catch (Exception exception)
            {

                log.Error(exception.Message, exception);
                throw;
            }

        }

        public void DeleteClient(int clientId)
        {
            try
            {
                //Validation
                var client = GetClientById(clientId);
                _context.Clients.DeleteObject(client);
                _context.SaveChanges();
            }

            catch (Exception exception)
            {
                log.Error(exception.Message, exception);
                throw;

            }
        }

        #endregion


    }
}
